/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.polarrose.wsf.controller;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.springframework.aop.support.AopUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;

import com.polarrose.wsf.action.WebServiceActionHandler;
import com.polarrose.wsf.stereotype.WebServiceAction;

public class AnnotationWebServiceController extends AbstractWebServiceController {
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Resource
	private ApplicationContext applicationContext;

	@PostConstruct
	public void initializeActions() {
		log.info("Initializing AnnotationWebServiceController; name = " + (name == null ? "default" : name));

		String[] beanNames = applicationContext.getBeanNamesForType(Object.class);
		for (String beanName : beanNames) {
			Class<?> actionType = AopUtils.getTargetClass(applicationContext.getBean(beanName));
			WebServiceAction webServiceAction = AnnotationUtils.findAnnotation(actionType, WebServiceAction.class);
			if (webServiceAction != null) {
				String webServiceName = webServiceAction.webServiceName();
				String[] webServiceNames = webServiceAction.webServiceNames();
				if (!isEmpty(webServiceName)) {
					log.warn("webServiceName parameter in @WebServiceAction is deprecated in action " + actionType.getName());
				}

				if (!isEmpty(webServiceName) && !containsOnlyEmptyName(webServiceNames)) {
					throw new RuntimeException("User only either webServiceName or webServiceNames in @WebServiceAction");
				}
				if (name == null && containsOnlyEmptyName(webServiceNames) && isEmpty(webServiceName)) {
					registerAction(beanName, webServiceAction.name(), webServiceAction.version());
				}
				if (name != null && isEmpty(webServiceName) && webServiceNames != null && contains(webServiceNames, name)) {
					registerAction(beanName, webServiceAction.name(), webServiceAction.version());
				}
				if (name != null && containsOnlyEmptyName(webServiceNames) && !isEmpty(webServiceName) && name.equals(webServiceName)) {
					registerAction(beanName, webServiceAction.name(), webServiceAction.version());
				}
			}
		}
	}

	private boolean containsOnlyEmptyName(String[] webServiceNames) {
		return webServiceNames != null && webServiceNames.length == 1 && "".equals(webServiceNames[0]);
	}

	private boolean isEmpty(String webServiceName) {
		return webServiceName == null || webServiceName.trim().length() == 0;
	}

	private void registerAction(String beanName, String name, String version) {
		registerAction(name, version, (WebServiceActionHandler<?, ?>) applicationContext.getBean(beanName));
	}

	private boolean contains(String[] webServiceNames, String name) {
		for (String s : webServiceNames) {
			if (s.equals(name)) {
				return true;
			}
		}
		return false;
	}

}
